﻿"use strict";
const db = require('../utils/db');
const clientMgr = require('./clientMgr');
const roomConf = require('./roomConf');
const crypto = require('../utils/crypto');
const socket = require('../base_net/socket');
const logger = require("../utils/logger");
const hallServer = require('../hall_server/hallServer');

var gl_mj = require( './games/gl_mj' );
var gy_mj = require( './games/gy_mj' );
var wd_nn = require( './games/wd_nn' );
var pk_dx = require( './games/pk_dx' );
var pk_zjh = require( './games/pk_zjh' );
var pk_sg = require( './games/pk_sg' );
var pk_sss = require( './games/pk_sss' );
var pk_dz = require( './games/pk_dz' );
var mj_nd = require( './games/mj_nd' );
var mj_fd = require( './games/mj_fd' );

var gameMgr = {};
gameMgr.gl_mj = gl_mj;
gameMgr.gy_mj = gy_mj;
gameMgr.wd_nn = wd_nn;
gameMgr.pk_dx = pk_dx;
gameMgr.pk_zjh = pk_zjh;
gameMgr.pk_sg = pk_sg;
gameMgr.pk_sss = pk_sss;
gameMgr.pk_dz = pk_dz;
gameMgr.mj_nd = mj_nd;
gameMgr.mj_fd = mj_fd;
var rooms = {};
var creatingRooms = {};
var disRoom = {};           //所有未解散房间定时器
var roomsCount = {};

var userLocation = {};
var roomCost = {};
var propCost = {};

function generateRoomId(){
	var roomId = "";
	for(var i = 0; i < 6; ++i){
		roomId += Math.floor(Math.random()*10);
	}
	return roomId;
}

function initRoomCost() {
    db.get_all_game_cost(function(rows) {
        for (var i = 0; i < rows.length; ++i) {
            var data = rows[i];
            var type = data.gameType;
            roomCost[type] = data;
        }
        logger.game_log("房间费用", roomCost);
    });
}

function initPropCost() {
    db.get_all_prop(function(rows) {
        for (var i = 0; i < rows.length; ++i) {
            var data = rows[i];
            var type = data.propName;
            propCost[type] = data;
        }
        logger.game_log("道具费用", propCost);
    });
}
initRoomCost();
initPropCost();

function payCost(userId, costPropId, totalCost) {
    if (costPropId == 1) {  // 钻石
        db.add_gem({userId: userId, gem: -totalCost});
    } else if (costPropId == 2) { // 房卡
        db.cost_roomCard(userId, totalCost);
    } else if (costPropId == 3) {
        db.cost_coins(userId, {area:""}, totalCost);
    } else {
        logger.error_log("未知的房间消耗类型", userId, costPropId);
    }
}

exports.canUseProp = function(userId, propName) {
    var prop = propCost[propName];
    logger.game_log(prop)
    if (!prop) {
        return true;
    }
    var rs = exports.getSeatUser(userId);
    if (!rs) {
        return false;
    }
    if (prop.costPropId == 1) {
        return rs.gems >= prop.costAmount;
    } else if (prop.costPropId == 2) { // 房卡
        return rs.roomCard >= prop.costAmount;
    } else if (prop.costPropId == 3) {
        return rs.coins >= prop.costAmount;
    }
    return true;
}

exports.costUseProp = function(userId, propName) {
    var prop = propCost[propName];
    if (!prop) {
        return;
    }
    payCost(userId, prop.costPropId, prop.costAmount);
}

exports.payGameCost = function(roomId) {
    var roomInfo = exports.getRoom(roomId);
    var conf = roomInfo.conf;
    var costData = roomCost[roomInfo.type];
    if (costData == null) return;

    var costPropId = costData.costPropId;
    var costPropAmount = costData.costPropAmount;
    if (conf.fufei == 1) {
        var owner = roomInfo.owner;
        var amount = 0;
        for(var i = 0; i < roomInfo.seats.length; ++i) {
            var rs = roomInfo.seats[i];
            if (rs.userId <= 0) continue;
            amount++;
        }
        logger.game_log("房主付费", roomInfo.type, owner, costPropId, amount * costPropAmount);
        payCost(owner, costPropId, amount * costPropAmount);
    } else {
        for(var i = 0; i < roomInfo.seats.length; ++i) {
            var rs = roomInfo.seats[i];
            if (rs.userId <= 0) continue;
            payCost(rs.userId, costPropId, costPropAmount);
            logger.game_log("AA付费", roomInfo.type, rs.userId, costPropId, costPropAmount);
        }
    }
}

function getGameCostCode(roomType, maxGameNum, fufeiType, roomNum, info) {
    if (roomCost[roomType] == null) {
        logger.game_log("未配置的房间类型", roomType);
        return 0;
    }
    // var rate = Math.floor(maxGameNum / 8);    // 每8局一个消耗
    var rate = maxGameNum;    // 每局一个消耗
    if (fufeiType == 1) {
        rate = roomNum * rate;
    }
    var costPropId = roomCost[roomType].costPropId;
    var costPropAmount = roomCost[roomType].costPropAmount;
    var totalCost = costPropAmount * rate;
    if (costPropId == 1) {  // 钻石
        if (info.gems < totalCost) {
            return 408;
        }
    } else if (costPropId == 2) { // 房卡
        if (info.roomCard < totalCost) {
            return 406;
        }
    } else if (costPropId == 3) {
        if (info.coins < totalCost) {
            return 407;
        }
    } else {
        logger.error_log("未知的房间消耗类型", roomType, costPropId);
    }
    return 0;
}

// function userPlayGameCost(roomType, maxGameNum, fufeiType, roomNum, userId) {
//     if (roomCost[roomType] == null) {
//         logger.game_log("未配置付费");
//         return;
//     }
//     // var rate = Math.floor(maxGameNum / 8);    // 每8局一个消耗
//     var rate = maxGameNum;    // 每局一个消耗
//     if (fufeiType == 1) {
//         rate = roomNum * rate;
//     }
//     var costPropId = roomCost[roomType].costPropId;
//     var costPropAmount = roomCost[roomType].costPropAmount;
//     var totalCost = costPropAmount * rate;
//     if (costPropId == 1) {  // 钻石
//         db.add_gem({userId: userId, gem: -totalCost});
//     } else if (costPropId == 2) { // 房卡
//         db.cost_roomCard(userId, totalCost);
//     } else if (costPropId == 3) {
//         db.cost_coins(userId, {area:""}, totalCost);
//     } else {
//         logger.error_log("未知的房间消耗类型");
//     }
//     return 0;
// }

exports.createRoom = function(creator,conf,callback,url){
    if(creator == null){
        logger.error_log("createRoom creator",creator);
        return;
    }
	var config = roomConf.parse(conf);
    logger.game_log("房间配置：", config);
	if(config == null){
		callback(401,null);
		return;
	}

    var roomId = generateRoomId();
    if(rooms[roomId] != null || creatingRooms[roomId] != null){
        return;
    }

    clientMgr.getUserInfo(creator,function (info) {
        if(info == null){
            logger.game_log(22222222222);
            return;
        }
        if (config.fufei) {
            var code = getGameCostCode(config.type, config.maxGames, config.fufei, config.roomNum, info);
            if (code != 0) {
                callback(code);
                return;
            }
        }
        // if (config.cost && config.cost > info.roomCard) {
        //     callback(406);
        //     return;
        // }
        // if (config.condition && config.condition > info.coins) {
        //     callback(407);
        //     return;
        // }
        creatingRooms[roomId] = true;
        var createTime = Date.now();
        var roomInfo = {
            roomId:roomId,
            type:config.type,
            owner:creator,
            numOfGames:0,
            createTime:createTime,
            seats:[],
            conf:config,
            url : url
        };
        var fnCreate = function(roomInfo2){
            roomInfo2.gameMgr = gameMgr[roomInfo2.conf.type];
            if(roomInfo2.gameMgr == null){
                callback(402,null);
                return 402;
            }
            for(var i = 0; i < roomInfo2.conf.roomNum; ++i) {
                roomInfo2.seats.push({
                    userId:0,
                    area : "",
                    score:0,
                    gems:0,
                    coins:0,
                    userName:"",
                    sit:0,
                    ready:0,
                    seatIndex:i,

                    numZiMo:0,
                    numJiePao:0,
                    numDianPao:0,
                    numAnGang:0,
                    numMingGang:0,
                });
            }
        }
        //写入数据库
        db.create_room(roomInfo,function(ret){
            delete creatingRooms[roomId];
            if(ret){
                fnCreate(roomInfo);
                roomAdd(roomInfo.conf.type);
                rooms[roomId] = roomInfo;
                callback(0,roomId,roomInfo);
            }
            else{
                callback(403,null);
            }
        });
    });

};

exports.destroy = function(roomId){
	if( disRoom[ roomId ] ) {
		//删除定时任务
		clearTimeout( disRoom[ roomId ] );
		delete disRoom[ roomId ];
	}
	var roomInfo = rooms[roomId];
    if(roomInfo == null)return;
	for(var i = 0; i < roomInfo.conf.roomNum; ++i){
		var userId = roomInfo.seats[i].userId;
		if(userId > 0){
			delete userLocation[userId];
            clientMgr.leaveRoom(roomId,i,userId,true);
		}
	}
	roomMinus(roomInfo.conf.type);
	delete rooms[roomId];
	db.delete_room(roomId);
    hallServer.delete_room(roomId);
};

exports.enterRoom = function(roomId,userId,area,callback){
	var fnTakeSeat = function(room,cb){
		if(exports.getUserRoomId(userId)){
			//已存在
            cb(0);
			return;
		}
		for(var i = 0; i < room.conf.roomNum; ++i) {
			var seat = room.seats[i];
			if(seat.userId <= 0){
                clientMgr.getUserInfo(userId,function (info) {
                    if(info == null)return;

                    if (room.conf.fufei && room.conf.fufei == 2) {
                        var code = getGameCostCode(room.conf.type, room.conf.maxGames, room.conf.fufei, room.conf.roomNum, info);
                        if (code != 0) {
                            callback(code);
                            return;
                        }
                    }
				    // if(room.conf.cost && room.conf.cost > info.roomCard){
                    //     cb(406);
                    //     return;
                    // }
                    // if(room.conf.condition && room.conf.condition > info.coins){
                    //     cb(407);
                    //     return;
                    // }
                    if(seat.userId > 0){
                        cb(408);
                        return;
                    }
                    seat.userId = userId;
                    seat.area = area;
                    userLocation[userId] = {
                        type : room.conf.type,
                        roomId:roomId,
                        seatIndex:i
                    };
                    seat.userName = crypto.toBase64(info.userName);
                    seat.coins = info.coins;
                    seat.gems = info.gems;
                    seat.headImg = info.headImg;
                    clientMgr.enterRoom(roomId,i,seat.userId,info.userName);
                    disRoomStop(roomId);

                    roomStateChange(roomId,room);
                    //正常
                    cb(0);

                });
				return;
			}
		}	
		//房间已满
        cb(405);
	};
	var room = rooms[roomId];
	if( room ){
		var ret = fnTakeSeat(room,callback);
	}
	else{
        callback(404);
    }
};

exports.exitRoom = function(userId){
    var location = userLocation[userId];
    if(location == null)
        return;

    var roomId = location.roomId;
    var seatIndex = location.seatIndex;
    var room = rooms[roomId];

    var seat = room.seats[seatIndex];
    seat.userId = 0;
    seat.area = "";
    seat.userName = "";
    seat.ready = 0;
    seat.sit = 0;

    delete userLocation[userId];
    clientMgr.leaveRoom(roomId,seatIndex,userId);
    roomStateChange(roomId,room);
};

exports.setStart = function (roomId) {
    //展示房间状态
    hallServer.setStart(roomId);
    
    // var roomInfo = rooms[roomId];
    // var conf = roomInfo.conf;
    // if (conf.fufei == 1) {
    //     userPlayGameCost(conf.type, conf.maxGames, conf.fufei, conf.roomNum, roomInfo.owner);
    // } else if (conf.fufei == 2) {
    //     for (var i = 0; i < roomInfo.seats.length; ++i) {
    //         var user = roomInfo.seats[i];
    //         if (user.userId <= 0 || user.sit == 0) continue;
    //         userPlayGameCost(conf.type, conf.maxGames, conf.fufei, conf.roomNum, user.userId);
    //     }
    // }
}
function roomStateChange (roomId,roomInfo) {
    var numOfPlayers = 0;
    var isBegin = true;
    var count = 0;
    for(var i = 0; i < roomInfo.seats.length; ++i){
    	var userId = roomInfo.seats[i].userId;
        if(userId > 0 && clientMgr.isOnline(userId)){
            numOfPlayers++;
        }
        if(userId > 0 && roomInfo.seats[i].ready == false){
            isBegin = false;
        }
        else if(userId > 0)count += 1;
    }
    //长时间没人上线解散房间
    if( numOfPlayers == 0  && roomInfo.owner != "999999"){
        disRoomStart(roomInfo.roomId);
    }
    if(isBegin && count > 1 && roomInfo.gameMgr && roomInfo.owner != "999999"){
        // roomInfo.gameMgr.gameBegin(roomInfo);
    }
    if(roomInfo){
        //展示房间状态
        hallServer.roomStateChange(roomId,roomInfo);
    }
}
exports.getRoomsCount = function(type){
	return roomsCount[type];
}
exports.getTotalRooms = function(){
	var count = 0;
	for(i in roomsCount){
        count += roomsCount[i];
	}
    return count;
};
function roomAdd(type){
	if(roomsCount[type] >= 0){
        roomsCount[type] ++;
	}
	else{
        roomsCount[type] = 1;
	}
}
function roomMinus(type){
    if(roomsCount[type] > 0){
        roomsCount[type] --;
    }
    else{
        roomsCount[type] = 0;
    }
}
exports.getRoom = function(roomId){
    return rooms[roomId];
};
exports.getSeatUser = function(userId) {
    var location = userLocation[userId];
    if (location != null) {
        var roomId = location.roomId;
        var seatIndex = location.seatIndex;
        var roomInfo = rooms[roomId];
        if (roomInfo == null) return;
        var user = roomInfo.seats[seatIndex];
        return user;
    }
};
exports.exitRoomAfterEnd = function(userId) {
    var roomId = exports.getUserRoomId(userId);
    if (roomId == null) return;
    var room = exports.getRoom(roomId);
    if (room == null) return;
    var roomInfo = rooms[roomId];
    if (roomInfo == null) return;

    var seatIndex = exports.getUserIndex(userId);
    // roomInfo.gameMgr.exitAfterEnd(roomInfo,seatIndex);

    logger.game_log("准备房间结束退出");
    if (roomInfo.owner == userId) {
        if(roomInfo.gameMgr.hasBegan(roomId)) {
            logger.game_log("房主无法直接退出游戏");
            roomInfo.gameMgr.exitAfterEnd(roomInfo,seatIndex);
        } else {
            logger.game_log("房主解散游戏");
            
            clientMgr.broadcastInRoom(socket.resp.dispress,"dispress",userId,false);
            clientMgr.kickAllInRoom(roomId);
            exports.destroy(roomId);
        }
    } else {
        if(roomInfo.gameMgr.hasBegan(roomId)){
            if (roomInfo.seats[seatIndex].sit == 1 || roomInfo.seats[seatIndex].ready == 1) {
                roomInfo.gameMgr.exitAfterEnd(roomInfo,seatIndex);
                logger.game_log("等房间结束退出");
            } else {
                exports.exitRoom(userId);
                logger.game_log("房间结束退出");
            }
        } else {
            exports.exitRoom(userId);
            logger.game_log("房间结束退出");
        }
    }
    roomStateChange(roomId, roomInfo);
}
exports.reconnect = function(userId) {
    var roomId = exports.getUserRoomId(userId);
    if (roomId) {
        disRoomStop(roomId);
    }
}
exports.getUserRoomId = function(userId){
	var location = userLocation[userId];
	if(location != null){
		return location.roomId;
	}
	return null;
};
exports.getUserIndex = function(userId){
    var location = userLocation[userId];
    if(location != null){
        return location.seatIndex;
    }
    return null;
};
exports.getRoomType = function(userId){
    var location = userLocation[userId];
    if(location != null){
        return location.type;
    }
    return null;
};
exports.isCreator = function(roomId,userId){
    var roomInfo = rooms[roomId];
    if(roomInfo == null){
        return false;
    }
    return roomInfo.owner == userId;
};
function disRoomStart ( roomId ) {
	if( disRoom[ roomId ] ) {
        clearTimeout( disRoom[ roomId ] );
    }
    //所有人都已经下线，增加定时任务，1小时没人上线，删除房间 60 * 1000
    disRoom[ roomId ] = setTimeout( function(){
        exports.destroy( roomId );
    }, 120 * 1000 );
};
function disRoomStop ( roomId ) {
    if( disRoom[ roomId ] ) {
        clearTimeout( disRoom[ roomId ] );
        delete disRoom[ roomId ];
    }
}